⚠️ Pokud nemáte stažený Git repozitář z lekce "L11: Bash skripty -- echo, proměnné", stáhněte si ho. Postup je hned na začátku.
Funkce zjednodušují a zpřehledňují skripty tím, že rozdělují program na menší části. Každá funkce provede definované příkazy a může vracet hodnotu. Funkce lze volat z hlavního programu, což umožňuje rozložit úkoly na části, které můžete v kódu opakovaně použít.
Před pokračováním si uvedeme příklad funkce, která pouze vypíše text (skript funkce.sh):
#!/bin/bash
hello()
{
echo "Nyní jsme ve funkci hello()"
}
echo "Nyní se zavolá funkce hello()..."
hello
echo "Nyní jsme zase mimo funkci hello()"
Funkce zde v našem konkrétním případě plní účel vypsání textu, který nás pouze informuje o tom, že je funkce prováděna.
Funkce samozřejmě může dělat mnohem komplikovanější úlohy, ale právě zde jen vytiskne text. Funkci vždy voláme napsáním jejího jména do programu, jejíž jméno může být libovolné. V našem programu se jmenuje hello, a volá se:
hello
Když je tento řádek vykonáván, bash prohledá skript, zda-li je v něm funkce hello(). Nalezne-li jí, tak provede příkazy, které jsou v ní zapsány.
Samotná funkce je určena svým názvem, po kterém následuje dvojice kulatých závorek ( ). Blok příkazů ve funkci je uzavřen složenými závorkami { }. Ty značí začátek a konec funkce. Veškerý kód funkce bude vykonán pouze, bude-li funkce zavolána.
Funkce by také měla být vždy definována ještě před tím, než bude zavolána:
hello()
{
echo "Nyní jsme ve funkci hello()"
}
Je též přípustné, že před názvem funkce může být slovo function:
function hello()
{
echo "Nyní jsme ve funkci hello()"
}
Skript se začne normálně provádět od začátku, jak jsme zvyklí, takže nic nového. Když ale narazí na konstrukci hello() nebo function hello() ví, že se jedná o definici funkce jménem hello. Zapamatuje si, že hello odkazuje na funkci a pokračuje v provádění příkazů po odpovídající složené závorce.
Dříve než funkci vyvoláte, vždy ji musíte nejprve definovat, podobně jako v jakémkoliv jiném jazyce. Protože se všechny skripty provádějí od začátku, umístíte všechny funkce před její první volání.
Při volání funkce jsou poziční parametry skriptu $*, $@, $#, $1, $2 atd. nahrazeny parametry funkce. Pomocí nich pak čtete parametry předané funkci. Po skončení funkce jsou hodnoty všech parametrů zase obnoveny. Tyto parametry se používají stejně jako proměnné. Příklad -- skript pozdrav.sh:
#!/bin/bash
pozdrav()
{
local jmeno=$1
local denni_doba=$2
echo "Dobre $denni_doba, $jmeno!"
}
# Volání funkce s konkrétními parametry
pozdrav "Pavle" "rano"
V tomto příkladu jsou $1 a $2 v těle funkce pozdrav nahrazeny skutečnými parametry předanými funkci. Funkce poté vypíše příslušný pozdrav. Po skončení funkce jsou hodnoty $1 a $2 zase obnoveny, takže neovlivní žádné proměnné mimo rozsah funkce.
Funkce mohou pomocí příkazu return vracet číselnou hodnotu. Pokud je potřeba vrátit řetězec, uloží se do proměnné, kterou lze po skončení funkce použít. Případně můžete řetězec vypsat příkazem echo a výsledek odchytit jako v následujícím příkladu:
#!/bin/bash
foo()
{
echo Ahoj
}
...
result="$(hello)"
Uvnitř shellu můžete za pomoci klíčového slova local deklarovat lokální proměnné. Proměnná pak existuje jen v rámci dané funkce. Jinak může funkce přistupovat k jiným proměnným shellu, které jsou v podstatě globální. Pokud má lokální proměnná stejný název jako globální, pak tuto proměnnou potlačí, ale jen v rámci příslušné funkce. Abychom si to demonstrovali, ukážeme si následující příklad - skript local.sh: :
#!/bin/bash
vzorovy_text="globální proměnná"
foo()
{
local vzorovy_text="lokální proměnná"
echo "Provádí se funkce foo"
echo $vzorovy_text
}
echo "Začátek skriptu"
echo $vzorovy_text
foo
echo "Konec skriptu"
echo $vzorovy_text
exit 0
Pokud funkce neobsahuje příkaz return, vrací návratový kód posledního provedeného příkazu.
V následujícím příkladu si ukážeme způsob předávání parametrů funkci a také způsob jakým mohou funkce vracet hodnoty true nebo false. Skript yes_no.sh:
#!/bin/bash
yes_or_no()
{
echo "Je tvé jméno $* ?"
while true
do
echo -n "Napiš ano nebo ne: "
read x
case "$x" in
a | ano ) return 0;;
n | ne ) return 1;;
* ) echo "Napiš ano nebo ne"
esac
done
}
echo "Původní parametr je $*"
if yes_or_no "$1"
then
echo "Ahoj $1, pěkné jméno"
else
echo "Nikdy"
fi
exit 0
Tento příklad funguje tak, že po spuštění skriptu je definována funkce yes_or_no, ale není provedena. V příkazu if provede skript funkci yes_or_no, které předá jako parametry zbytek řádku, kde zápis $1 nahradí prvním parametrem skriptu. Funkce pak pracuje s těmito parametry, které jsou nyní uloženy v pozičních proměnných $1, $2 atd. a vrátí hodnotu volajícímu příkazu. Příkaz if v závislosti na návratové hodnotě provede příslušní příkaz.
Tři úkoly na procvičení práce s funkcemi v Bashi:
calc.sh) Vytvoř funkci kalkulacka, která bude přijímat dva číselné argumenty a jeden operátor (+, -, *, /). Funkce provede příslušnou operaci a výsledek vypíše. Dělení bude celočíselné, o čemž skript uživatele informuje -- za výsledkem bude (int).
Příklad použití:
./calc.sh 5 + 3
./calc.sh 5 / 2
Výstup:
Výsledek operace 5 + 3 je 8
Výsledek operace 5 / 2 je 2 (int)
Nápověda:
case pro rozlišení operátorů.$((...)).pass.sh) Zadání: Vytvořte funkci kontrola_hesla, která zkontroluje, zda zadané heslo splňuje určitá kritéria (např. minimální délka, obsah číslic a písmen). Funkce vrátí hodnotu 0 (úspěch) nebo 1 (neúspěch).
Možná kostra skriptu:
#!/bin/bash
kontrola_hesla() {
if [[ ${#1} -lt 8 ]]; then
return 1
fi
# Další podmínky pro číslice, speciální znaky atd.
return 0
}
# Použití:
if kontrola_hesla "MojeHeslo123"; then
echo "Heslo je v pořádku."
else
echo "Heslo nesplňuje požadavky."
fi
rand.sh) Zadání: Vytvoř funkci generuj_heslo, která přijme délku hesla a generuje náhodné heslo složené z malých a velkých písmen a číslic.
heslo=$(generuj_heslo 12)
echo "Vygenerované heslo: $heslo"
Nápověda:
shuf pro náhodné výběry znaků z předem definovaného řetězce.for pro vytvoření hesla požadované délky.Možná kostra skriptu:
#!/bin/bash
generuj_heslo() {
heslo=""
for i in $(seq 1 $1); do
heslo="$heslo${RANDOM:0:1}"
done
echo "$heslo"
}
# Použití:
heslo=$(generuj_heslo 12)
echo "Vygenerované heslo: $heslo"